package com.gmss.crawler.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gmss.crawler.module.retraction.company.domain.RCompany;
import com.gmss.crawler.module.retraction.company.service.IRCompanyService;
import com.gmss.crawler.module.retraction.paper.domain.RPaper;
import com.gmss.crawler.module.retraction.paperauthor.domain.RPaperAuthor;
import com.gmss.crawler.module.retraction.paperauthor.service.IRPaperAuthorService;
import com.gmss.crawler.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 自动化测试工具，实现爬取撤稿论文工作
 */
@Slf4j
@Service
public class AutoRetractionCrawlerService {

    @Resource
    private IRPaperAuthorService iRPaperAuthorService;

    @Resource
    private IRCompanyService iRCompanyService;

    public static void main(String[] args) throws InterruptedException {
        RPaper rPaper = new RPaper();
        String title = "Inverse Matrix Auto-Search Technique for the RTS MIMO OTA Test—Part 1: Theory";
        System.out.println(replaceAllSpecialSymbols(title));
//        rPaper.setTitle(title);
//        new AutoRetractionCrawlerService().webOfScienceSearch(rPaper);
    }

    public Map<String, Object> webOfScienceSearch(RPaper rPaper) throws InterruptedException {
        // chrome浏览器
        System.setProperty("webdriver.chrome.driver", "C:\\Users\\user\\Downloads\\chromedriver_win32_2\\chromedriver.exe");
        WebDriver webDriver = new ChromeDriver();
        // firefox浏览器
//        System.setProperty("webdriver.gecko.driver", "C:\\Users\\user\\Downloads\\firefox\\geckodriver.exe");
//        WebDriver webDriver = new FirefoxDriver();
        webDriver.manage().window().maximize();
        webDriver.manage().deleteAllCookies();
        // 与浏览器同步非常重要，必须等待浏览器加载完毕
        webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        try {
            //打开目标地址
            webDriver.get("https://www.webofscience.com/wos/alldb/basic-search");
        } catch (Exception e) {
            webDriver.quit();
        }
        try {
            Thread.sleep(CommonUtils.randomRange(1000, 1000 * 4));
            webDriver.findElement(By.id("onetrust-accept-btn-handler")).click();
        } catch (Exception e) {
            Thread.sleep(CommonUtils.randomRange(1000, 1000 * 4));
            webDriver.findElement(By.id("onetrust-accept-btn-handler")).click();
        }
        //
        String title = rPaper.getTitle();
        title = replaceAllSpecialSymbols(title);
        //输入账号 密码并登陆系统
        Thread.sleep(CommonUtils.randomRange(1000 * 1, 1000 * 5));
        webDriver.findElement(By.xpath("/html/body/app-wos/div/div/main/div/div[2]/app-input-route/app-search-home/div/div" +
                "/app-input-route/app-search-basic/app-search-form/form" +
                "/div[1]/app-search-row/div/div[2]/input")).sendKeys(title);
        Thread.sleep(CommonUtils.randomRange(1000 * 2, 1000 * 5));
        webDriver.findElement(By.cssSelector("button[data-ta='run-search'][class='mat-focus-indicator cdx-but-md search uppercase-button mat-flat-button mat-button-base mat-primary']")).click();
        Map<String, Object> paperMap = new HashMap<>();
        try {
            Thread.sleep(CommonUtils.randomRange(1000 * 1, 1000 * 3));
//            List<WebElement> webElementList = webDriver.findElements(By.cssSelector("a[data-ta='summary-record-title-link'][class='title title-link font-size-18 ng-star-inserted']"));
            List<WebElement> webElementList = webDriver.findElements(By.tagName("app-summary-title"));
            if (CollectionUtils.isNotEmpty(webElementList)) {
                int size = webElementList.size();
                if (webElementList.size() > 3) {
                    size = 4;
                }
                for (int i = 0; i < size; i++) {
                    WebElement webElement = webElementList.get(i).findElement(By.tagName("h3")).findElement(By.cssSelector("a[class='title title-link font-size-18 ng-star-inserted']"));
                    String paperDetailUrl = webElement.getAttribute("href");
                    webOfScienceListHtml(paperDetailUrl, paperMap, rPaper, title);
                    if (MapUtils.isNotEmpty(paperMap) && paperMap.containsKey("doiMatching") && (Boolean)paperMap.get("doiMatching")) {
                        break;
                    }
                }
            }
        } catch (Exception e) {
            log.error("webOfScienceSearch r_paper_id：{} Exception：{}", rPaper.getId(), e);
        }
        //暂停二秒钟后关闭
//        Thread.sleep(500);
        webDriver.quit();
        return paperMap;
    }

    private static String replaceAllSpecialSymbols(String title) {
        return title.replaceAll("‘", "'").replaceAll("’", "'").replaceAll("κ", "kappa")
                .replaceAll("β", "beta").replaceAll("ß", "beta").replaceAll("–", "-").replaceAll("—", "-")
                .replaceAll("α", "alpha").replaceAll("“", "\"").replaceAll("”", "\"")
                .replaceAll("\\?", "").replaceAll("：", "").replaceAll(":", "").replaceAll("ö", "o");
    }

    public void webOfScienceListHtml(String url, Map<String, Object> paperMap, RPaper rPaper, String title) throws InterruptedException {

        System.setProperty("webdriver.chrome.driver", "C:\\Users\\user\\Downloads\\chromedriver_win32_2\\chromedriver.exe");
        WebDriver webDriver = new ChromeDriver();
//        System.setProperty("webdriver.gecko.driver", "C:\\Users\\user\\Downloads\\chromedriver_win32\\geckodriver.exe");
//        WebDriver webDriver = new FirefoxDriver();
        webDriver.manage().window().maximize();
        webDriver.manage().deleteAllCookies();
        // 与浏览器同步非常重要，必须等待浏览器加载完毕
        webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

        try {
            //打开目标地址
            webDriver.get(url);
        } catch (Exception e) {
            webDriver.quit();
        }
        Thread.sleep(CommonUtils.randomRange(1000, 1000 * 4));
        //
        try {
            webDriver.findElement(By.id("onetrust-accept-btn-handler")).click();
        } catch (Exception e) {
            Thread.sleep(CommonUtils.randomRange(1000, 1000 * 3));
            webDriver.findElement(By.id("onetrust-accept-btn-handler")).click();
        }

        // 摘要
        WebElement abstractWebElement = null;
        try {
            abstractWebElement = webDriver.findElement(By.id("FullRTa-abstract-basic"));
            if (null != abstractWebElement) {
                String abstractText = abstractWebElement.getText();
                paperMap.put("abstractData", abstractText);
            }
        } catch (Exception e) {

        }

        try {
            String titleText = webDriver.findElement(By.id("FullRTa-fullRecordtitle-0")).getText();
            if (StringUtils.isNotBlank(titleText)) {
                titleText = replaceAllSpecialSymbols(titleText);
                titleText = CommonUtils.replaceBlank(titleText);
                title = CommonUtils.replaceBlank(title);
            }

            if (StringUtils.isBlank(titleText) || !StringUtils.contains(titleText.toLowerCase(), title.toLowerCase())) {
                if (CommonUtils.getSimilarityRatio(titleText.toLowerCase(), title.toLowerCase()) < 90) {
                    paperMap = new HashMap<>();
                    // 标题不对应 ，关闭浏览器返回。
                    webDriver.quit();
                    return;
                }
            }

            String addressNum = webDriver.findElement(By.id("address_1")).findElement(By.tagName("span")).findElement(By.tagName("sup")).findElement(By.tagName("span")).getText();
            addressNum = CommonUtils.replaceBlank(addressNum);
            if (!StringUtils.isNumeric(addressNum)) {
                paperMap = new HashMap<>();
                // 无隶属机构地址，关闭浏览器返回。
                webDriver.quit();
                return;
            }

        } catch (Exception e) {
            paperMap = new HashMap<>();
            // 标题不对应 或 无隶属机构地址，关闭浏览器返回。
            webDriver.quit();
            return;
        }

        try {
            String fullRTaDOI = webDriver.findElement(By.id("FullRTa-DOI")).getText();
            if (StringUtils.isNotBlank(fullRTaDOI) && StringUtils.isNotBlank(rPaper.getOriginalDoi()) && StringUtils.equals(fullRTaDOI, rPaper.getOriginalDoi())) {
                // doi匹配结果，相同为true;
                paperMap.put("doiMatching", true);

            }
            if (StringUtils.isNotBlank(fullRTaDOI) && StringUtils.isNotBlank(rPaper.getRetractionOrOtherNoticesDoi()) && StringUtils.equals(fullRTaDOI, rPaper.getRetractionOrOtherNoticesDoi())) {
                // doi匹配结果，相同为true;
                paperMap.put("doiMatching", true);
            }
        } catch (Exception e) {
        }

        paperMap.put("relatedLinks", url);
        List<Map<String, Object>> authorList = new ArrayList<>();
//        Map<String, Object> paperMap = new HashMap<>();

        // 关键词
        String keywordsText = webDriver.findElement(By.cssSelector("app-full-record-keywords[class='ng-star-inserted']")).getText();
        if (StringUtils.isNotBlank(keywordsText)) {


            WebElement authorKeywordsId = null;
            try {
                authorKeywordsId = webDriver.findElement(By.id("FRkeywordsTa-authorKeywordsLabel"));
            } catch (Exception e) {

            }
            WebElement authorKeywordsPlusId = null;
            try {
                authorKeywordsPlusId = webDriver.findElement(By.id("FRkeywordsTa-keyWordsPlusLabel"));
            } catch (Exception e) {
            }

            List<String> authroKeywordListStr = new ArrayList<>();
            if (null != authorKeywordsId) {
                List<WebElement> authorKeywordsWebElementList = new ArrayList<>();
                try {
                    authorKeywordsWebElementList = webDriver.findElements(By.xpath("/html/body/app-wos/div/div/main/div/div[2]/app-input-route" +
                            "/app-full-record-home/div[2]/div[1]/app-full-record/" +
                            "/div/app-full-record-keywords/div[1]/span"));
                } catch (Exception e) {
                }

                if (CollectionUtils.isNotEmpty(authorKeywordsWebElementList)) {
                    for (WebElement webElement : authorKeywordsWebElementList) {
                        String text = webElement.getText();
                        if (StringUtils.isNotBlank(text)) {
                            authroKeywordListStr.add(text);
                        }
                    }
                }
            }
            if (null != authorKeywordsPlusId) {
                List<WebElement> authorKeywordsWebElementList = new ArrayList<>();
                try {
                    authorKeywordsWebElementList = webDriver.findElements(By.xpath("/html/body/app-wos/div/div/main/div/div[2]/app-input-route" +
                            "/app-full-record-home/div[2]/div[1]/app-full-record/" +
                            "/div/app-full-record-keywords/div[2]/span"));
                } catch (Exception e) {
                }

                if (CollectionUtils.isNotEmpty(authorKeywordsWebElementList)) {
                    for (WebElement webElement : authorKeywordsWebElementList) {
                        String text = webElement.getText();
                        if (StringUtils.isNotBlank(text)) {
                            authroKeywordListStr.add(text);
                        }
                    }
                }
            }

            if (CollectionUtils.isNotEmpty(authroKeywordListStr))
                paperMap.put("authorKeywrods", StringUtils.join(authroKeywordListStr, ";"));
        }
        List<WebElement> authorNameElementList = null;
        try {
            authorNameElementList = webDriver.findElement(By.id("SumAuthTa-MainDiv-author-en")).findElements(By.cssSelector("span[class='value ng-star-inserted']"));
        } catch (Exception e) {
        }

        if (CollectionUtils.isNotEmpty(authorNameElementList)) {
            for (int i = 0; i < authorNameElementList.size(); i++) {
                Map<String, Object> authorMap = new HashMap<>();
                WebElement webElement = authorNameElementList.get(i);
                String authorName = null;
                String authorAltName = null;
                List<String> authorInformationOrderList = new ArrayList<>();
                try {
                    if (authorNameElementList.size() > 10 && i == 10) {
                        // 作者姓名超出10个人会隐藏，点击按钮显示隐藏数据
                        try {
                            Thread.sleep(1000);
                            webDriver.findElement(By.id("SumAuthTa-FrToggle-author-en"))
                                    .findElement(By.tagName("button"))
                                    .click();
                        } catch (Exception e) {
                            webDriver.findElement(By.id("SumAuthTa-FrToggle-author-en"))
                                    .findElement(By.tagName("button"))
                                    .click();
                        }
                    }
                    authorAltName = webElement.findElement(By.tagName("a")).findElement(By.tagName("span")).getText();
                    authorName = webElement.findElement(By.cssSelector("span[class='font-size-14 value']")).getText();
//                    order = webElement.findElement(By.cssSelector("button[class='mat-tooltip-trigger address_link sup-style borderLess-button ng-star-inserted']")).getText();
                    List<WebElement> orderList = webElement.findElements(By.cssSelector("button[class='mat-tooltip-trigger address_link sup-style borderLess-button ng-star-inserted']"));
                    if (CollectionUtils.isNotEmpty(orderList)) {
                        for (WebElement orderWebElement : orderList) {
                            String orderText = orderWebElement.getText().replaceAll(", ", "");
                            authorInformationOrderList.add(orderText);
//                            System.out.println(orderText);
                        }
                    }
                } catch (Exception e) {
                }
                // 作者其它姓名
                if (StringUtils.isNotBlank(authorName))
                    authorMap.put("authorName", authorName);
                // 作者其它姓名格式（英文）
                if (StringUtils.isNotBlank(authorAltName))
                    authorMap.put("authorAltName", authorAltName);
                // 作者顺序
                authorMap.put("order", (i + 1));
                // 作者对应工作单位的序列号
                if (CollectionUtils.isNotEmpty(authorInformationOrderList)) {
                    authorMap.put("authorInformationOrder", authorInformationOrderList);
                }
                authorList.add(authorMap);
            }
        }


//        if (CollectionUtils.isNotEmpty(authorList)) {
//            paperMap.put("authorList", authorList);
//            for (Map<String, Object> authorMap : authorList) {
//                if (authorMap.containsKey("authorInformationOrder")) {
//                    // 地址：超过5条会隐藏，触发点击按钮显示隐藏
//                    List<String> authorInformationOrderList = (List<String>) authorMap.get("authorInformationOrder");
//                    if (authorInformationOrderList.contains("6")) {
//                        webDriver.findElement(By.id("FRACTa-authorAddressView")).click();
//                        break;
//                    }
//                }
//            }
//        }

        try {
            Thread.sleep(1000);
            // 地址：超过5条会隐藏，触发点击按钮显示隐藏
            webDriver.findElement(By.id("FRACTa-authorAddressView")).click();
        } catch (Exception e) {
        }
        try {
            if (CollectionUtils.isNotEmpty(authorNameElementList) && authorNameElementList.size() > 10) {
                webDriver.findElement(By.id("SumAuthTa-FrToggle-author-en"))
                        .findElement(By.tagName("button"))
                        .click();
            }
            // 作者姓名，点击按钮隐藏数据
        } catch (Exception e) {
        }

        // 通讯作者，作者工作单位
        List<WebElement> authorInformationList = webDriver.findElements(By.cssSelector("div[class='author-info-section ng-star-inserted']"));
        if (CollectionUtils.isNotEmpty(authorInformationList)) {
            for (int i = 0; i < authorInformationList.size(); i++) {
                //
                String text = null;
                List<WebElement> reprintList = null;
                try {
                    text = authorInformationList.get(i).findElement(By.cssSelector("h3[class='label colonMark']")).getText();
                    reprintList = authorInformationList.get(i).findElements(By.cssSelector("div[class='ng-star-inserted']"));
                } catch (Exception e) {
                }

                if (CollectionUtils.isNotEmpty(reprintList)) {
                    for (int j = 0; j < reprintList.size(); j++) {
                        String authorName = null;
                        String address = null;
                        if (StringUtils.isNotBlank(text) && StringUtils.equalsAny(text, "Reprint Address", "通讯作者地址")) {
                            try {
                                authorName = reprintList.get(j)
                                        .findElement(By.cssSelector("div[class='flex-display-align-center']"))
                                        .findElement(By.xpath("div[2]"))
                                        .findElement(By.cssSelector("span[class='ng-star-inserted']"))
                                        .findElement(By.cssSelector("span[class='value']")).getText();
                            } catch (Exception e) {
                            }

                            if (StringUtils.isNotBlank(authorName)) {
                                if (CollectionUtils.isNotEmpty(authorList)) {
                                    String finalReprintAuthorName = authorName;
                                    authorList.forEach(authorMap -> {
                                        if (StringUtils.equalsIgnoreCase(finalReprintAuthorName, authorMap.get("authorName").toString())) {
                                            // 是否为通讯作者，1：是
                                            authorMap.put("reportAuthor", 1);
                                        }
                                    });
                                }
                            }
                        }
                        if (StringUtils.isNotBlank(text) && StringUtils.equalsAny(text, "Addresses", "地址")) {
                            try {
                                List<WebElement> addressWebElementList = reprintList.get(j)
                                        .findElements(By.cssSelector("a[class='no-underline-link margin-left-30--reversible ng-star-inserted']"));
                                if (CollectionUtils.isNotEmpty(addressWebElementList)) {
                                    String orderText = null;
                                    for (int k = 0; k < addressWebElementList.size(); k++) {
                                        WebElement webElement = addressWebElementList.get(k);
                                        try {
                                            orderText = webElement.findElement(By.cssSelector("span[class='label cdx-font--weight-600 ng-star-inserted']")).getText().trim();
                                            address = webElement.findElement(By.cssSelector("span[class='value padding-right-5--reversible']")).getText();
                                        } catch (Exception e) {
                                        }
                                    }

                                    if (StringUtils.isNotBlank(orderText)) {
                                        if (CollectionUtils.isNotEmpty(authorList)) {
                                            String finalOrderText = orderText;
                                            String finalAddress = address;
                                            authorList.forEach(authorMap -> {
                                                List<String> list2 = authorMap.containsKey("authorInformationOrder") ? (List<String>) authorMap.get("authorInformationOrder") : null;
                                                if (CollectionUtils.isNotEmpty(list2) && list2.contains(finalOrderText)) {
                                                    if (authorMap.containsKey("workCompany")) {
                                                        Set<String> workCompanySet = (Set<String>) authorMap.get("workCompany");
                                                        workCompanySet.add(finalAddress);
                                                        authorMap.put("workCompany", workCompanySet);
                                                    } else {
                                                        Set<String> workCompanySet = new HashSet<>();
                                                        workCompanySet.add(finalAddress);
                                                        authorMap.put("workCompany", workCompanySet);
                                                    }
                                                }
//                                                if (StringUtils.equalsIgnoreCase(finalOrderText, authorMap.get("authorInformationOrder").toString())) {
//                                                    authorMap.put("workCompany", finalAddress);
//                                                }
                                            });
                                        }
                                    }
                                }
                            } catch (Exception e) {
                            }
                        }
                    }
                }
            }
        }

        try {
            webDriver.findElement(By.id("FRACTa-authorAddressView")).click();
        } catch (Exception e) {
        }

        try {

            if (CollectionUtils.isNotEmpty(authorList)) {
//            LambdaQueryWrapper<RPaperAuthor> lambdaQueryWrapper = new LambdaQueryWrapper();
//            lambdaQueryWrapper.eq(RPaperAuthor::getRPaperId, rPaper.getId());
//            int count = iRPaperAuthorService.count(lambdaQueryWrapper);
//            if (count > 0) {
//                LambdaUpdateWrapper<RPaperAuthor> lambdaUpdateWrapper = new LambdaUpdateWrapper();
//                lambdaUpdateWrapper.eq(RPaperAuthor::getRPaperId, rPaper.getId());
//                iRPaperAuthorService.remove(lambdaUpdateWrapper);
//            }


                authorList.forEach(authorMap -> {
                    Set<String> workCompanySet = authorMap.containsKey("workCompany") ? (Set<String>) authorMap.get("workCompany") : null;
                    List<Long> workCompanyIds = new ArrayList<>();
                    if (null != workCompanySet && workCompanySet.size() > 0) {
                        for (String workCompany : workCompanySet) {
                            LambdaQueryWrapper<RCompany> rCompanyLambdaQueryWrapper = new LambdaQueryWrapper<>();
                            rCompanyLambdaQueryWrapper.eq(RCompany::getCompanyName, workCompany);
                            RCompany workCompanyList = iRCompanyService.getOne(rCompanyLambdaQueryWrapper);
                            if (null != workCompanyList && null != workCompanyList.getId()) {
                                workCompanyIds.add(workCompanyList.getId());
                            } else {
                                RCompany rCompany = new RCompany().builder()
                                        .companyName(workCompany)
                                        .build();
                                iRCompanyService.save(rCompany);
                                workCompanyIds.add(rCompany.getId());
                            }
                        }
                    }

                    LambdaQueryWrapper<RPaperAuthor> queryWrapper = new LambdaQueryWrapper();
                    queryWrapper.eq(RPaperAuthor::getRPaperId, rPaper.getId());
                    if (authorMap.containsKey("authorName")) {
                        queryWrapper.eq(RPaperAuthor::getAuthorName, authorMap.get("authorName"));
                    } else {
                        return;
                    }
//                    if (authorMap.containsKey("authorAltName")) {
//                        queryWrapper.eq(RPaperAuthor::getAuthorAltName, authorMap.get("authorAltName"));
//                    }
                    if (CollectionUtils.isNotEmpty(workCompanyIds)) {
                        workCompanyIds = workCompanyIds.stream().sorted(((o1, o2) -> Long.compare(o1, o2))).collect(Collectors.toList());
//                        queryWrapper.in(RPaperAuthor::getRCompanyId, workCompanyIds);
                    }
                    RPaperAuthor queryRPaperAuthor = iRPaperAuthorService.getOne(queryWrapper);
                    if (null != queryRPaperAuthor) {
                        RPaperAuthor rPaperAuthor = new RPaperAuthor().builder()
                                .id(queryRPaperAuthor.getId())
                                .build();
                        getrPaperAuthor(authorMap, workCompanyIds, rPaperAuthor);
                        iRPaperAuthorService.updateById(rPaperAuthor);

                    } else {
                        RPaperAuthor rPaperAuthor = new RPaperAuthor().builder()
                                .rPaperId(rPaper.getId())
                                .build();
                        getrPaperAuthor(authorMap, workCompanyIds, rPaperAuthor);
                        iRPaperAuthorService.save(rPaperAuthor);
                    }
                });
            }
        } catch (Exception e) {
            log.error("AutoRetractionCrawlerService saveDatabases rPaperID：{} Exception:{}", rPaper.getId(), e);
        } finally {
            //暂停二秒钟后关闭
//            Thread.sleep(500);
            webDriver.quit();
        }

    }

    private RPaperAuthor getrPaperAuthor(Map<String, Object> authorMap, List<Long> workCompanyIds, RPaperAuthor rPaperAuthor) {
        if (authorMap.containsKey("reportAuthor")) {
            rPaperAuthor.setReportAuthor((Integer) authorMap.get("reportAuthor"));
        }
        if (authorMap.containsKey("authorName") && ObjectUtils.isNotEmpty(authorMap.get("authorName"))) {
            rPaperAuthor.setAuthorName(authorMap.get("authorName").toString());
        }
        if (authorMap.containsKey("authorAltName") && ObjectUtils.isNotEmpty(authorMap.get("authorAltName"))) {
            rPaperAuthor.setAuthorAltName(authorMap.get("authorAltName").toString());
        }
        if (authorMap.containsKey("order")) {
            rPaperAuthor.setAuthorOther((Integer) authorMap.get("order"));
        }
        if (CollectionUtils.isNotEmpty(workCompanyIds)) {
            rPaperAuthor.setRCompanyId(StringUtils.join(workCompanyIds, ","));
        }
        return rPaperAuthor;
    }
}
